#pragma once


namespace bit
{

	template<class T1, class T2>
	struct Reverse_iterator
	{
		typedef Reverse_iterator<T1, T2> self;
		T1 _it;

		Reverse_iterator(T1 pos)
			:_it(pos)
		{}

		//Reverse_iterator(const T1& pos)
		//{
		//	_it = pos;
		//}
		//
		self& operator++()
		{
			--_it;
			return *this;
		}

		self operator++(int)
		{
			self tmp(_it);
			--_it;
			return tmp;
		}

		self& operator--()
		{
			++_it;
			return *this;
		}

		self operator--(int)
		{
			self tmp(_it);
			++_it;
			return tmp;
		}

		T2& operator*()const
		{
			return *(_it);
		}
		//
		bool operator!=(const self& pos)
		{
			return _it != pos._it;
		}

		bool operator==(const self& pos)
		{
			return _it == pos._it;
		}

		T1 operator->()
		{
			return _it;
		}
	};

	template<typename T>
	class vector
	{
	public:

		typedef Reverse_iterator<T*, T> reverse_iterator;
		typedef Reverse_iterator<const T*, const T> const_reverse_iterator;
		typedef T* iterator;
		typedef const T* const_iterator;
		size_t size()const
		{
			return finish - start;
		}

		void push_back(const T& val)
		{
			if (finish == end_of_storage)
			{
				size_t newcapacity = start == nullptr ? 4 : 2 * capacity();
				reserve(newcapacity);
			}
			*finish = val;
			finish++;
			//insert(end(), val);
		}

		void pop_back()
		{
			assert(size() > 0);
			--finish;
		}

		size_t capacity()const
		{
			return end_of_storage - start;
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				T* newstart = new T[n];
				if (start)
				{
					for (size_t i = 0; i < size(); i++)
					{
						newstart[i] = start[i];
					}
					finish = newstart + size();
					end_of_storage = newstart + n;
					delete[]start;
					start = newstart;
				}
				else
				{
					finish = newstart;
					end_of_storage = newstart + n;
					start = newstart;
				}
			}
		}

		void resize(size_t n)
		{
			if (n > capacity())
			{
				reserve(n);
			}
			else if (n > size())
			{
				int i = n - size();
				while (i)
				{
					*finish = T();
					finish++;
					i--;
				}
			}
			else
			{
				finish = start + n;
			}
		}

		iterator begin()
		{
			return start;
		}

		iterator end()
		{
			return finish;
		}

		const_iterator begin()const
		{
			return start;
		}

		const_iterator end()const
		{
			return finish;
		}

		reverse_iterator rbegin()
		{
			return reverse_iterator(finish - 1);
		}

		const_reverse_iterator crbegin()const
		{
			return const_reverse_iterator(finish - 1);
		}

		reverse_iterator rend()
		{
			return reverse_iterator(start - 1);
		}

		const_reverse_iterator crend()const
		{
			return const_reverse_iterator(start - 1);
		}

		T& operator[](size_t n)
		{
			assert(n < size());
			return start[n];
		}

		const T& operator[](size_t n)const
		{
			assert(n < size());
			return start[n];
		}

		iterator insert(iterator pos, const T& x)
		{
			assert(pos <= finish);
			assert(pos >= start);
			int oldpos = pos - begin();
			if (finish == end_of_storage)
			{
				int newcapacity = capacity() == 0 ? 4 : 2 * capacity();
				reserve(newcapacity);
			}
			pos = begin() + oldpos;
			int i = 1;
			while (end() - i >= pos)
			{
				*(end() + 1 - i) = *(end() - i);
				i++;
			}
			*pos = x;
			finish++;
			return pos;
		}


		iterator erase(iterator pos)
		{
			assert(pos < end());
			assert(pos >= begin());
			int i = 0;
			while (pos + i + 1 < end())
			{
				*(pos + i) = *(pos + i + 1);
				i++;
			}
			finish--;
			return pos;
		}

		//vector<T>& operator=(vector<T>& vc)
		//{
		//	if (start != vc.start)
		//	{
		//		reserve(vc.capacity());
		//		int i = 0;
		//		while (vc.start + i < vc.finish)
		//		{
		//			start[i] = vc[i];
		//			i++;
		//		}
		//		finish = start + i;
		//	}
		//	return *this;
		//}

		vector<T>& operator=(vector<T> vc)
		{
			swap(vc);
			return *this;
		}

		~vector()
		{
			if (start)
			{
				delete[]start;
				start = nullptr;
				finish = nullptr;
				end_of_storage = nullptr;
			}
		}

		void swap(vector<T>& val)
		{
			std::swap(start, val.start);
			std::swap(finish, val.finish);
			std::swap(end_of_storage, val.end_of_storage);
		}

		vector() = default;

		vector(const vector<T>& val)
		{
			start = new T[val.capacity()];
			finish = start;
			end_of_storage = start + val.capacity();
			for (auto e : val)
			{
				push_back(e);
			}
		}
		template <class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			reserve(last - first);
			while (first < last)
			{
				push_back(*first);
				first++;
			}
		}
		vector(initializer_list<T> il)
		{
			reserve(il.size());
			for (auto e : il)
			{
				push_back(e);
			}
		}
		vector(size_t n, const T& val = T())
		{
			reserve(n);
			while (n)
			{
				push_back(val);
				n--;
			}
		}
		vector(int n, const T& val = T())
		{
			reserve(n);
			while (n)
			{
				push_back(val);
				n--;
			}
		}

	private:
		T* start = nullptr;
		T* finish = nullptr;
		T* end_of_storage = nullptr;
	};

}